import React, {PureComponent} from 'react'
import * as THREE from 'three'
import OrbitControls from 'three-orbitcontrols'
import {DDSLoader} from "three/examples/jsm/loaders/DDSLoader"
import {MTLLoader} from "three/examples/jsm/loaders/MTLLoader"
import {OBJLoader} from "three/examples/jsm/loaders/OBJLoader"

import "./index.less"
import {Spin} from "antd"
import threeCompose from "./compose"
import PropTypes from "prop-types"

export default @threeCompose
class ThreeStage extends PureComponent {

  constructor(props) {
    super(props)
  }

  initThree = () => {
    const {width, height, basePath, mtlName, objUrl, $progress, $loading} = this.props

    //定义渲染器
    let renderer = new THREE.WebGLRenderer({antialias: true})

    //定义摄影机
    let camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000)

    //定义场景
    let scene = new THREE.Scene()

    //定义灯光
    let light = new THREE.AmbientLight(0xFFFFFF)

    //定义控制器
    let controls

    //定义加载器
    let manager = new THREE.LoadingManager()

    init()

    function animation() {
      renderer.render(scene, camera)
      controls.update()
      requestAnimationFrame(animation)
    }

    function init() {
      renderer.setSize(width, height)
      const root = (this.props.element || document.getElementById('zr-three-stage'))
      root.appendChild(renderer.domElement)
      renderer.setClearColor(0xffffff, 1.0)

      camera.position.set(0, 0, 300)
      camera.up.set(0, 1, 0)
      camera.lookAt(0, 0, 0)

      light.position.set(300, 300, 0)
      scene.add(light)

      //添加物件
      controls = new OrbitControls(camera, renderer.domElement)
      controls.target = new THREE.Vector3(0, 0, 0)
      controls.minDistance = 200
      controls.maxDistance = 500

      manager.addHandler(/\.dds$/i, new DDSLoader())
      $loading(true)
      new MTLLoader(manager)
        .setPath(basePath)
        //加载材质
        .load(mtlName, materials => {
          materials.preload()
          //加载模型
          new OBJLoader(manager)
            .setMaterials(materials)
            .load(objUrl, (object) => {
                object.position.y = -95
                scene.add(object)
                setTimeout(() => $loading(false), 100)
              },
              xhr => {
                const percentComplete = xhr.loaded / xhr.total * 100
                $progress(Math.floor(percentComplete))
              }, error => {
                console.info(error)
              })
        })
    }

    animation()
  }

  render() {

    const {width, height, progress, error, loading} = this.props
    const style = {width: `${width}px`, minHeight: `${height}px`}

    return <div className={'zr-three-stage-container'} style={style}>
      {
        loading ?
          <div className={'zr-three-progress-container'}>
            <div>
              <Spin size={"large"}/>
            </div>
            <h3>正在加载({progress}%)</h3>
          </div>
          : undefined
      }
      <div id={'zr-three-stage'} style={style}></div>
    </div>

  }

  componentDidMount() {
    setTimeout(() => this.initThree(), 100)
  }
}


ThreeStage.propTypes = {
  element: PropTypes.element,
  width: PropTypes.number,
  height: PropTypes.number,
  /*
  * 材质文件目录
  * */
  basePath: PropTypes.string,
  /*
  * 材质文件名,相对于材质文件目录
  * */
  mtlName: PropTypes.string,
  /*
  * 模型文件路径
  * */
  objUrl: PropTypes.string,
}
